#include "ImaMqInterface.h"
#include "ImaGlobals.h"
#include "ImaConstants.h"
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <errno.h>

ImaMqInterface* ImaMqInterface::mpMqInterface = NULL;

ImaMqInterface* ImaMqInterface::getInstance(ImaConf& conf) {
	if(mpMqInterface == NULL) {
		LOG(debug, __FILE__, __LINE__, "creating Posix Message Queue interface object");
		mpMqInterface = new ImaMqInterface(conf);
	}
	return mpMqInterface;
}

ImaMqInterface::ImaMqInterface(ImaConf& conf): mImMsgQId(0), mRegConfCodeMsgQId(0), mNewPasswordMsgQId(0) {
	LOG(debug, __FILE__, __LINE__, "ImaMqInterface::ImaMqInterface() called");

	key_t key;

    /*if ((key = ftok(IMA_APP_NAME, 'x')) == -1) {
		char log_msg[1024];
		sprintf(log_msg, "Failed to create message queue key with key name: %s and queuename: %s", IMA_APP_NAME, conf.mXmppMqName);
        LOG(error, __FILE__, __LINE__, log_msg);
        exit(1);
    } */

   // if((mMsgQId = msgget(key, 0644 | IPC_CREAT)) == -1) {
    if((mImMsgQId = msgget(conf.mSysVImMsgQKey, 0644 | IPC_CREAT)) == -1) {//TODO: replace this line with above one in future
		char log_msg[1024];
		sprintf(log_msg, "Failed to create message queue with key: %d", conf.mSysVImMsgQKey);
        LOG(error, __FILE__, __LINE__, log_msg);
        exit(1);
    } else {
		char log_msg[1024];
		sprintf(log_msg, "Created message queue with key %d", conf.mSysVImMsgQKey);
		LOG(info, __FILE__, __LINE__, log_msg);
	}

	if((mRegConfCodeMsgQId = msgget(conf.mSysVRegConfCodeMsgQKey, 0644 | IPC_CREAT)) == -1) {//TODO: replace this line with above one in future
		char log_msg[1024];
		sprintf(log_msg, "Failed to create message queue with key: %d", conf.mSysVRegConfCodeMsgQKey);
        LOG(error, __FILE__, __LINE__, log_msg);
        exit(1);
    } else {
		char log_msg[1024];
		sprintf(log_msg, "Created message queue with key %d", conf.mSysVRegConfCodeMsgQKey);
		LOG(info, __FILE__, __LINE__, log_msg);
	}

	if((mNewPasswordMsgQId = msgget(conf.mSysVNewPasswordQKey, 0644 | IPC_CREAT)) == -1) {//TODO: replace this line with above one in future
		char log_msg[1024];
		sprintf(log_msg, "Failed to create message queue with key: %d", conf.mSysVNewPasswordQKey);
        LOG(error, __FILE__, __LINE__, log_msg);
        exit(1);
    } else {
		char log_msg[1024];
		sprintf(log_msg, "Created message queue with key %d", conf.mSysVNewPasswordQKey);
		LOG(info, __FILE__, __LINE__, log_msg);
	}

	if((mUserFeedbackMsgQId = msgget(conf.mSysVUserFeedbackQKey, 0644 | IPC_CREAT)) == -1) {//TODO: replace this line with above one in future
		char log_msg[1024];
		sprintf(log_msg, "Failed to create message queue with key: %d", conf.mSysVUserFeedbackQKey);
        LOG(error, __FILE__, __LINE__, log_msg);
        exit(1);
    } else {
		char log_msg[1024];
		sprintf(log_msg, "Created message queue with key %d", conf.mSysVUserFeedbackQKey);
		LOG(info, __FILE__, __LINE__, log_msg);
	}
}

ImaMqInterface::~ImaMqInterface() {
	LOG(debug, __FILE__, __LINE__, "ImaMqInterface::~ImaMqInterface() called");
}

bool ImaMqInterface::enqueueImId(const char* pImId) {
	LOG(debug, __FILE__, __LINE__, "ImaMqInterface::enqueueImId");

	struct msgbuf buf;
	buf.msg_type = 1;			//TODO: handle this later
	strcpy(buf.msg_buf, pImId);

	size_t len = strlen(buf.msg_buf);

	if(msgsnd(mImMsgQId, &buf, len, 0) == -1) { /* NO +1 for '\0' because it is going to be used by python script that is causing some problem when the string is NULL terminated*/
		char log_msg[1024];
		sprintf(log_msg, "Failed to enqueue the imid: %s into the message queue. Error message: %s", buf.msg_buf, strerror(errno));
		LOG(error, __FILE__, __LINE__, log_msg);
		return false;
	}

	char log_msg[1024];
	sprintf(log_msg, "Successfully enqueued IM ID: %s into the message queue", buf.msg_buf);
	LOG(debug, __FILE__, __LINE__, log_msg);

	return true;
}


bool ImaMqInterface::enqueueConfCode(const char* pUserEmailId, const char* pConfCode, bool bEMailAndImSame) {
	LOG(debug, __FILE__, __LINE__, "ImaMqInterface::enqueueConfCode");

	struct msgbuf buf;
	buf.msg_type = 1;			//TODO: handle this later
	if(bEMailAndImSame) {
		sprintf(buf.msg_buf, "%s#%s#1", pUserEmailId, pConfCode);
	} else {
		sprintf(buf.msg_buf, "%s#%s#0", pUserEmailId, pConfCode);
	}

	size_t len = strlen(buf.msg_buf);

	if(msgsnd(mRegConfCodeMsgQId, &buf, len+1, 0) == -1) { /* +1 for '\0' */
		char log_msg[1024];
		sprintf(log_msg, "Failed to enqueue the Registration confirmation code: %s into the message queue. Error message: %s", buf.msg_buf, strerror(errno));
		LOG(error, __FILE__, __LINE__, log_msg);
		return false;
	}

	char log_msg[1024];
	sprintf(log_msg, "Successfully enqueued Registration confirmation code: %s into the message queue", buf.msg_buf);
	LOG(debug, __FILE__, __LINE__, log_msg);

	return true;
}

bool ImaMqInterface::enqueueNewPassword(const char* pUserEmailId, const char* pNewPassword) {
	LOG(debug, __FILE__, __LINE__, "ImaMqInterface::enqueueNewPassword");

	struct msgbuf buf;
	buf.msg_type = 1;			//TODO: handle this later
	sprintf(buf.msg_buf, "%s#%s", pUserEmailId, pNewPassword);

	size_t len = strlen(buf.msg_buf);

	if(msgsnd(mNewPasswordMsgQId, &buf, len+1, 0) == -1) { /* +1 for '\0' */
		char log_msg[1024];
		sprintf(log_msg, "Failed to enqueue the new password for the user: %s into the message queue. Error message: %s", pUserEmailId, strerror(errno));
		LOG(error, __FILE__, __LINE__, log_msg);
		return false;
	}

	char log_msg[1024];
	sprintf(log_msg, "Successfully enqueued the new password for the user: %s into the message queue", pUserEmailId);
	LOG(debug, __FILE__, __LINE__, log_msg);

	return true;
}


bool ImaMqInterface::enqueueUserFeedback(const char* pSenderName, 
		const char* pSenderEmailId, const char* pMsgSub, const char* pMsgBody) {
	LOG(debug, __FILE__, __LINE__, "ImaMqInterface::enqueueUserFeedback");

	struct msgbuf buf;
	buf.msg_type = 1;			//TODO: handle this later
	snprintf(buf.msg_buf, MSGQBUFSZ - 1, "%s#%s#%s#%s", pSenderName, pSenderEmailId, pMsgSub, pMsgBody);

	size_t len = strlen(buf.msg_buf);

	if(msgsnd(mUserFeedbackMsgQId, &buf, len+1, 0) == -1) { /* +1 for '\0' */
		char log_msg[1024];
		sprintf(log_msg, "Failed to enqueue user feedback into the message queue. Error message: %s", strerror(errno));
		LOG(error, __FILE__, __LINE__, log_msg);
		return false;
	}

	char log_msg[1024];
	sprintf(log_msg, "Successfully enqueued the user feedback into the message queue");
	LOG(debug, __FILE__, __LINE__, log_msg);

	return true;

}

